home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 051-075 / 068 / mg1b / random.c < prev    next >
C/C++ Source or Header  |  1995-03-13  |  14KB  |  552 lines

  1. /*
  2.  *        Assorted commands.
  3.  * The file contains the command
  4.  * processors for a large assortment of unrelated
  5.  * commands. The only thing they have in common is
  6.  * that they are all command processors.
  7.  */
  8. #include    "def.h"
  9.  
  10. /*
  11.  * Display a bunch of useful information about
  12.  * the current location of dot. The character under the
  13.  * cursor (in octal), the current line, row, and column, and
  14.  * approximate position of the cursor in the file (as a percentage)
  15.  * is displayed. The column position assumes an infinite position
  16.  * display; it does not truncate just because the screen does.
  17.  * This is normally bound to "C-X =".
  18.  */
  19. /*ARGSUSED*/
  20. showcpos(f, n, k) {
  21.     register LINE    *clp;
  22.     register long    nchar;
  23.     long        cchar;
  24.     register int    nline, row;
  25.     int        cline, cbyte;    /* Current line/char/byte */
  26.     int        ratio;
  27.     KEY        keychar();
  28.  
  29.     clp = lforw(curbp->b_linep);        /* Collect the data.    */
  30.     nchar = 0;
  31.     nline = 0;
  32.     for (;;) {
  33.         ++nline;            /* Count this line    */
  34.         if (clp == curwp->w_dotp) {
  35.             cline = nline;        /* Mark line        */
  36.             cchar = nchar + curwp->w_doto;
  37.             if (curwp->w_doto == llength(clp))
  38.                 cbyte = '\n';
  39.             else
  40.                 cbyte = lgetc(clp, curwp->w_doto);
  41.         }
  42.         nchar += llength(clp) + 1;    /* Now count the chars    */
  43.         if (clp == curbp->b_linep) break ;
  44.         clp = lforw(clp);
  45.     }
  46.     row = curwp->w_toprow;            /* Determine row.    */
  47.     clp = curwp->w_linep;
  48.     while (clp!=curbp->b_linep && clp!=curwp->w_dotp) {
  49.         ++row;
  50.         clp = lforw(clp);
  51.     }
  52.     ++row;                    /* Convert to origin 1.    */
  53.     /*NOSTRICT*/    
  54.     /* nchar can't be zero (because of the "bonus" \n at end of file) */
  55.     ratio = (100L*cchar) / nchar;
  56.     ewprintf("Char: %c (0%o)  point=%ld(%d%%)  line=%d  row=%d  col=%d",
  57.         (int) keychar(cbyte, FALSE), cbyte, cchar, ratio, cline, row,
  58.         getcolpos());
  59.     return (TRUE);
  60. }
  61.  
  62. getcolpos() {
  63.     register int    col, i, c;
  64.  
  65.     col = 0;                /* Determine column.    */
  66.     for (i=0; i<curwp->w_doto; ++i) {
  67.         c = lgetc(curwp->w_dotp, i);
  68.         if (
  69. #ifdef    NOTAB
  70.             !(mode & MNOTAB) &&
  71. #endif
  72.             c == '\t')
  73.             col |= 0x07;
  74.         else if (ISCTRL(c) != FALSE)
  75.             ++col;
  76.         ++col;
  77.     }
  78.     return col + 1;                /* Convert to origin 1.    */
  79. }
  80. /*
  81.  * Twiddle the two characters on either side of
  82.  * dot. If dot is at the end of the line twiddle the
  83.  * two characters before it. Return with an error if dot
  84.  * is at the beginning of line; it seems to be a bit
  85.  * pointless to make this work. This fixes up a very
  86.  * common typo with a single stroke. Normally bound
  87.  * to "C-T". This always works within a line, so
  88.  * "WFEDIT" is good enough.
  89.  */
  90. /*ARGSUSED*/
  91. twiddle(f, n, k) {
  92.     register LINE    *dotp;
  93.     register int    doto, odoto;
  94.     register int    cl;
  95.     register int    cr;
  96.  
  97.     dotp = curwp->w_dotp;
  98.     odoto = doto = curwp->w_doto;
  99.     if (doto==llength(dotp) && --doto<0)
  100.         return (FALSE);
  101.     cr = lgetc(dotp, doto);
  102.     if (--doto < 0)
  103.         return (FALSE);
  104.     cl = lgetc(dotp, doto);
  105.     lputc(dotp, doto+0, cr);
  106.     lputc(dotp, doto+1, cl);
  107.     if (odoto != llength(dotp)) ++(curwp->w_doto);
  108.     lchange(WFEDIT);
  109.     return (TRUE);
  110. }
  111.  
  112. /*
  113.  * Quote the next character, and
  114.  * insert it into the buffer. All the characters
  115.  * are taken literally, with the exception of the newline,
  116.  * which always has its line splitting meaning. The character
  117.  * is always read, even if it is inserted 0 times, for
  118.  * regularity.
  119.  */
  120. /*ARGSUSED*/
  121. quote(f, n, k) {
  122.     register int    s;
  123.     register KEY    c;
  124.  
  125.     if (kbdmop != NULL) c = (KEY) *kbdmop++;
  126.     else c = getkey(KQUOTE);
  127.     if (n < 0)
  128.         return (FALSE);
  129.     if (n == 0)
  130.         return (TRUE);
  131.     if (c == '\n') {
  132.         do {
  133.             s = lnewline();
  134.         } while (s==TRUE && --n);
  135.         return (s);
  136.     }
  137.     return (linsert((RSIZE) n, (char) c));
  138. }
  139.  
  140. /*
  141.  * Ordinary text characters are bound to this function,
  142.  * which inserts them into the buffer. Characters marked as control
  143.  * characters (using the CTRL flag) may be remapped to their ASCII
  144.  * equivalent. This makes TAB (C-I) work right, and also makes the
  145.  * world look reasonable if a control character is bound to this
  146.  * this routine by hand. Any META or CTLX flags on the character
  147.  * are discarded. This is the only routine that actually looks
  148.  * the the "k" argument.
  149.  */
  150. /*ARGSUSED*/
  151. selfinsert(f, n, k) {
  152.     register int    c;
  153.  
  154.     if (n < 0)
  155.         return (FALSE);
  156.     if (n == 0)
  157.         return (TRUE);
  158.     c = k & KCHAR;
  159.     if ((k&KCTRL)!=0 && c>='@' && c<='_')    /* ASCII-ify.        */
  160.         c -= '@';
  161.     return (linsert((RSIZE) n, c));
  162. }
  163.  
  164. /*
  165.  * Open up some blank space. The basic plan
  166.  * is to insert a bunch of newlines, and then back
  167.  * up over them. Everything is done by the subcommand
  168.  * procerssors. They even handle the looping. Normally
  169.  * this is bound to "C-O".
  170.  */
  171. /*ARGSUSED*/
  172. openline(f, n, k) {
  173.     register int    i;
  174.     register int    s;
  175.  
  176.     if (n < 0)
  177.         return (FALSE);
  178.     if (n == 0)
  179.         return (TRUE);
  180.     i = n;                    /* Insert newlines.    */
  181.     do {
  182.         s = lnewline();
  183.     } while (s==TRUE && --i);
  184.     if (s == TRUE)                /* Then back up overtop    */
  185.         s = backchar(f, n, KRANDOM);    /* of them all.        */
  186.     return (s);
  187. }
  188.  
  189. /*
  190.  * Insert a newline.
  191.  * If you are at the end of the line and the
  192.  * next line is a blank line, just move into the
  193.  * blank line. This makes "C-O" and "C-X C-O" work
  194.  * nicely, and reduces the ammount of screen
  195.  * update that has to be done. This would not be
  196.  * as critical if screen update were a lot
  197.  * more efficient.
  198.  */
  199. /*ARGSUSED*/
  200. newline(f, n, k) {
  201.     register LINE    *lp;
  202.     register int    s;
  203.  
  204.     if (n < 0)
  205.         return (FALSE);
  206.     while (n--) {
  207.         lp = curwp->w_dotp;
  208.         if (llength(lp) == curwp->w_doto
  209.         && lp != curbp->b_linep
  210.         && llength(lforw(lp)) == 0) {
  211.             if ((s=forwchar(FALSE, 1, KRANDOM)) != TRUE)
  212.                 return (s);
  213.         } else if ((s=lnewline()) != TRUE)
  214.             return (s);
  215.     }
  216.     return (TRUE);
  217. }
  218.  
  219. /*
  220.  * Delete blank lines around dot.
  221.  * What this command does depends if dot is
  222.  * sitting on a blank line. If dot is sitting on a
  223.  * blank line, this command deletes all the blank lines
  224.  * above and below the current line. If it is sitting
  225.  * on a non blank line then it deletes all of the
  226.  * blank lines after the line. Normally this command
  227.  * is bound to "C-X C-O". Any argument is ignored.
  228.  */
  229. /*ARGSUSED*/
  230. deblank(f, n, k) {
  231.     register LINE    *lp1;
  232.     register LINE    *lp2;
  233.     register RSIZE    nld;
  234.  
  235.     lp1 = curwp->w_dotp;
  236.     while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
  237.         lp1 = lp2;
  238.     lp2 = lp1;
  239.     nld = (RSIZE) 0;
  240.     while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
  241.         ++nld;
  242.     if (nld == 0)
  243.         return (TRUE);
  244.     curwp->w_dotp = lforw(lp1);
  245.     curwp->w_doto = 0;
  246.     return (ldelete((RSIZE)nld, KNONE));
  247. }
  248. /*
  249.  * Delete any whitespace around dot, then insert a space.
  250.  */
  251. /*ARGSUSED*/
  252. justone(f, n, k) {
  253.     (VOID) delwhite(f, n, k);
  254.     return linsert((RSIZE) 1, ' ');
  255. }
  256. /*
  257.  * Delete any whitespace around dot.
  258.  */
  259. /*ARGSUSED*/
  260. delwhite(f, n, k) {
  261.     register int    col, c, s;
  262.  
  263.     col = curwp->w_doto;
  264.     while ((c = lgetc(curwp->w_dotp, col)) == ' ' || c == '\t')
  265.         ++col;
  266.     do
  267.         if ((s = backchar(FALSE, 1, KRANDOM)) == FALSE) break;
  268.     while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ' || c == '\t') ;
  269.  
  270.     if (s == TRUE) (VOID) forwchar(FALSE, 1, KRANDOM);
  271.     (VOID) ldelete((RSIZE)(col - curwp->w_doto), KNONE);
  272.     return (TRUE);
  273. }
  274. /*
  275.  * Insert a newline, then enough
  276.  * tabs and spaces to duplicate the indentation
  277.  * of the previous line. Assumes tabs are every eight
  278.  * characters. Quite simple. Figure out the indentation
  279.  * of the current line. Insert a newline by calling
  280.  * the standard routine. Insert the indentation by
  281.  * inserting the right number of tabs and spaces.
  282.  * Return TRUE if all ok. Return FALSE if one
  283.  * of the subcomands failed. Normally bound
  284.  * to "C-J".
  285.  */
  286. /*ARGSUSED*/
  287. indent(f, n, k) {
  288.     register int    nicol;
  289.     register int    c;
  290.     register int    i;
  291.  
  292.     if (n < 0)
  293.         return (FALSE);
  294.     while (n--) {
  295.         nicol = 0;
  296.         for (i=0; i<llength(curwp->w_dotp); ++i) {
  297.             c = lgetc(curwp->w_dotp, i);
  298.             if (c!=' ' && c!='\t')
  299.                 break;
  300.             if (c == '\t')
  301.                 nicol |= 0x07;
  302.             ++nicol;
  303.         }
  304.         if (lnewline() == FALSE || ((
  305. #ifdef    NOTAB
  306.             mode&MNOTAB) ? linsert((RSIZE)nicol, ' ')==FALSE : (
  307. #endif
  308.             ((i=nicol/8)!=0 && linsert((RSIZE) i, '\t')==FALSE) ||
  309.             ((i=nicol%8)!=0 && linsert((RSIZE) i,  ' ')==FALSE))))
  310.             return (FALSE);
  311.     }
  312.     return (TRUE);
  313. }
  314.  
  315. /*
  316.  * Delete forward. This is real
  317.  * easy, because the basic delete routine does
  318.  * all of the work. Watches for negative arguments,
  319.  * and does the right thing. If any argument is
  320.  * present, it kills rather than deletes, to prevent
  321.  * loss of text if typed with a big argument.
  322.  * Normally bound to "C-D".
  323.  */
  324. /*ARGSUSED*/
  325. forwdel(f, n, k) {
  326.     if (n < 0)
  327.         return (backdel(f, -n, KRANDOM));
  328.     if (f != FALSE) {            /* Really a kill.    */
  329.         if ((lastflag&CFKILL) == 0)
  330.             kdelete();
  331.         thisflag |= CFKILL;
  332.     }
  333.     return (ldelete((RSIZE) n, f ? KFORW : KNONE));
  334. }
  335.  
  336. /*
  337.  * Delete backwards. This is quite easy too,
  338.  * because it's all done with other functions. Just
  339.  * move the cursor back, and delete forwards.
  340.  * Like delete forward, this actually does a kill
  341.  * if presented with an argument.
  342.  */
  343. /*ARGSUSED*/
  344. backdel(f, n, k) {
  345.     register int    s;
  346.  
  347.     if (n < 0)
  348.         return (forwdel(f, -n, KRANDOM));
  349.     if (f != FALSE) {            /* Really a kill.    */
  350.         if ((lastflag&CFKILL) == 0)
  351.             kdelete();
  352.         thisflag |= CFKILL;
  353.     }
  354.     if ((s=backchar(f, n, KRANDOM)) == TRUE)
  355.         s = ldelete((RSIZE) n, f ? KFORW : KNONE);
  356.     return (s);
  357. }
  358.  
  359. /*
  360.  * Kill line. If called without an argument,
  361.  * it kills from dot to the end of the line, unless it
  362.  * is at the end of the line, when it kills the newline.
  363.  * If called with an argument of 0, it kills from the
  364.  * start of the line to dot. If called with a positive
  365.  * argument, it kills from dot forward over that number
  366.  * of newlines. If called with a negative argument it
  367.  * kills any text before dot on the current line,
  368.  * then it kills back abs(arg) lines.
  369.  */
  370. /*ARGSUSED*/
  371. killline(f, n, k) {
  372.     register RSIZE    chunk;
  373.     register LINE    *nextp;
  374.     register int    i, c;
  375.  
  376.     if ((lastflag&CFKILL) == 0)        /* Clear kill buffer if    */
  377.         kdelete();            /* last wasn't a kill.    */
  378.     thisflag |= CFKILL;
  379.     if (f == FALSE) {
  380.         for (i = curwp->w_doto; i < llength(curwp->w_dotp); ++i)
  381.             if ((c = lgetc(curwp->w_dotp, i)) != ' ' && c != '\t')
  382.                 break;
  383.         if (i == llength(curwp->w_dotp))
  384.             chunk = llength(curwp->w_dotp)-curwp->w_doto + 1;
  385.         else {
  386.             chunk = llength(curwp->w_dotp)-curwp->w_doto;
  387.             if (chunk == 0)
  388.                 chunk = 1;
  389.         }
  390.     } else if (n > 0) {
  391.         chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
  392.         nextp = lforw(curwp->w_dotp);
  393.         i = n;
  394.         while (--i) {
  395.             if (nextp == curbp->b_linep)
  396.                 break;
  397.             chunk += llength(nextp)+1;
  398.             nextp = lforw(nextp);
  399.         }
  400.     } else {                /* n <= 0        */
  401.         chunk = curwp->w_doto;
  402.         curwp->w_doto = 0;
  403.         i = n;
  404.         while (i++) {
  405.             if (lback(curwp->w_dotp) == curbp->b_linep)
  406.                 break;
  407.             curwp->w_dotp = lback(curwp->w_dotp);
  408.             curwp->w_flag |= WFMOVE;
  409.             chunk += llength(curwp->w_dotp)+1;
  410.         }
  411.     }
  412.     /*
  413.      * KFORW here is a bug. Should be KBACK/KFORW, but we need to
  414.      * rewrite the ldelete code (later)?
  415.      */
  416.     return (ldelete(chunk,  KFORW));
  417. }
  418.  
  419. /*
  420.  * Yank text back from the kill buffer. This
  421.  * is really easy. All of the work is done by the
  422.  * standard insert routines. All you do is run the loop,
  423.  * and check for errors. The blank
  424.  * lines are inserted with a call to "newline"
  425.  * instead of a call to "lnewline" so that the magic
  426.  * stuff that happens when you type a carriage
  427.  * return also happens when a carriage return is
  428.  * yanked back from the kill buffer.
  429.  * An attempt has been made to fix the cosmetic bug
  430.  * associated with a yank when dot is on the top line of
  431.  * the window (nothing moves, because all of the new
  432.  * text landed off screen).
  433.  */
  434. /*ARGSUSED*/
  435. yank(f, n, k) {
  436.     register int    c;
  437.     register int    i;
  438.     register LINE    *lp;
  439.     register int    nline;
  440.  
  441.     if (n < 0)
  442.         return (FALSE);
  443.     nline = 0;                /* Newline counting.    */
  444.     while (n--) {
  445.         isetmark();            /* mark around last yank */
  446.         i = 0;
  447.         while ((c=kremove(i)) >= 0) {
  448.             if (c == '\n') {
  449.                 if (newline(FALSE, 1, KRANDOM) == FALSE)
  450.                     return (FALSE);
  451.                 ++nline;
  452.             } else {
  453.                 if (linsert((RSIZE) 1, c) == FALSE)
  454.                     return (FALSE);
  455.             }
  456.             ++i;
  457.         }
  458.     }
  459.     lp = curwp->w_linep;            /* Cosmetic adjustment    */
  460.     if (curwp->w_dotp == lp) {        /* if offscreen insert.    */
  461.         while (nline-- && lback(lp)!=curbp->b_linep)
  462.             lp = lback(lp);
  463.         curwp->w_linep = lp;        /* Adjust framing.    */
  464.         curwp->w_flag |= WFHARD;
  465.     }
  466.     return (TRUE);
  467. }
  468. /*
  469.  * Commands to toggle the five modes. Without an argument, sets the
  470.  * mode on, with an argument, sets the mode off.
  471.  */
  472. /*ARGSUSED*/
  473. bsmapmode(f, n, k) {
  474.  
  475.     if ((mode&MBSMAP) != MBSMAP) mode |= MBSMAP;
  476.     else mode &= ~MBSMAP;
  477.     upmodes((BUFFER *) NULL);
  478.     return TRUE;
  479. }
  480.  
  481. /*ARGSUSED*/
  482. flowmode(f, n, k) {
  483.     if ((mode&MFLOW) != MFLOW) mode |= MFLOW;
  484.     else mode &= ~MFLOW;
  485.     upmodes((BUFFER *) NULL);
  486.     return TRUE;
  487. }
  488.  
  489. /*ARGSUSED*/
  490. indentmode(f, n, k) {
  491.  
  492.     if ((mode&MINDENT) != MINDENT) {
  493.         mode |= MINDENT;
  494.         if ((binding[KCTRL|'M'] = symlookup("newline-and-indent"))
  495.             == NULL)
  496.             panic("no newline-and-indent in indentmode");
  497.         if ((binding[KCTRL|'J'] = symlookup("insert-newline")) == NULL)
  498.             panic("no insert-newline in indentmode");
  499.     } else {
  500.         mode &= ~MINDENT;
  501.         if ((binding[KCTRL|'M'] = symlookup("insert-newline")) == NULL)
  502.             panic("no insert-newline in indentmode");
  503.         if ((binding[KCTRL|'J'] = symlookup("newline-and-indent"))
  504.             == NULL)
  505.             panic("no newline-and-indent in indentmode");
  506.     }
  507.     upmodes((BUFFER *) NULL);
  508.     return TRUE;
  509. }    
  510.  
  511. /*ARGSUSED*/
  512. fillmode(f, n, k) {
  513.  
  514.     if ((mode&MFILL) != MFILL) {
  515.         mode |= MFILL;
  516.         if ((binding[' '] = symlookup("insert-with-wrap")) == NULL)
  517.             panic("no insert-with-wrap in fillmode");
  518.     } else {
  519.         mode &= ~MFILL;
  520.         if ((binding[' '] = symlookup("self-insert-command")) == NULL)
  521.             panic("no self-insert-command in fillmode");
  522.     }
  523.     upmodes((BUFFER *) NULL);
  524.     return TRUE;
  525. }
  526. #ifdef  NOTAB
  527.  
  528. space_tabpos(f, n, k)
  529. int f, n;
  530. {
  531.     int stat;
  532.  
  533.     if(n<0) return FALSE;
  534.     if(n==0) return TRUE;
  535.     return linsert(((RSIZE)n<<3) - (curwp->w_doto & 7), ' ');
  536. }
  537.  
  538. notabmode(f, n, k) {
  539.     if((mode&MNOTAB) != MNOTAB) {
  540.         mode |= MNOTAB;
  541.         if ((binding[KCTRL|'I'] = symlookup("space-to-tabstop")) == NULL)
  542.             panic("no space-to-tabstop in notabmode");
  543.     } else {
  544.         mode &= ~ MNOTAB;
  545.         if ((binding[KCTRL|'I'] = symlookup("self-insert-command")) == NULL)
  546.             panic("no self-insert-command in notabmode");
  547.     }
  548.     upmodes((BUFFER *) NULL);
  549.     return TRUE;
  550. }
  551. #endif
  552.